from protocol.codec import write_uint, encode_bcd
from typing import Dict, Any, Tuple
import logging


def detect_header_version(body_attr: int) -> str:
    """根据消息体属性自动识别header版本
    
    Args:
        body_attr: 消息体属性值
        
    Returns:
        "2013" 或 "2019"
    """
    # bit14=1 表示有版本标识字段（2019版本）
    has_version_flag = (body_attr >> 14) & 0x01
    return "2019" if has_version_flag else "2013"


def build_common_config(terminal_phone: str = None) -> dict:
    """构建common配置，处理SIM卡号等通用参数"""
    # 使用传入的SIM卡号，如果没有提供则使用默认值
    if terminal_phone is None:
        terminal_phone = '13800138000'
    
    return {
        'terminal_phone': {
            'value': terminal_phone,
            'digits': 20
        }
    }


def _build_msg_body_attr_2013(body_length: int) -> int:
    """构建2013版本的消息体属性
    
    2013版本：
    bit0-9: 消息体长度
    bit10-12: 数据加密方式 (000表示不加密)
    bit13: 分包 (0表示不分包)
    bit14: 保留 (0)
    bit15: 保留 (0)
    """
    if body_length < 0 or body_length > 0x3FF:
        raise ValueError('消息体长度超过10位字段可表示范围(<=1023)')
    # bit14=0，表示2013版本（无版本标识字段）
    attr = body_length & 0x03FF
    return attr


def _build_msg_body_attr_2019(body_length: int) -> int:
    """构建2019版本的消息体属性
    
    2019版本：
    bit0-9: 消息体长度
    bit10-12: 数据加密方式 (000表示不加密)
    bit13: 分包 (0表示不分包)
    bit14: 版本标识 (1表示有版本号字段)
    bit15: 保留 (0)
    """
    if body_length < 0 or body_length > 0x3FF:
        raise ValueError('消息体长度超过10位字段可表示范围(<=1023)')
    # bit14=1，表示2019版本（有版本标识字段）
    attr = (1 << 14) | (body_length & 0x03FF)
    return attr


def _build_msg_body_attr(body_length: int) -> int:
    """构建消息体属性（兼容旧代码，默认2019版本）"""
    return _build_msg_body_attr_2019(body_length)


def build_header_2013(frame_id: int, body_length: int, common: dict, state: dict) -> bytes:
    """构建2013版本的协议头
    
    结构（12字节）：
    - 消息ID (WORD, 2字节)
    - 消息体属性 (WORD, 2字节, bit14=0)
    - 终端手机号 (BCD[6], 6字节)
    - 消息流水号 (WORD, 2字节)
    """
    # 消息ID WORD
    msg_id = write_uint(frame_id, 2)
    
    # 消息体属性 WORD（bit14=0，表示2013版本）
    body_attr_value = _build_msg_body_attr_2013(body_length)
    body_attr = write_uint(body_attr_value, 2)
    
    # 终端手机号 BCD[6]（12位数字，6字节）
    phone_cfg = common.get('terminal_phone', {})
    phone_value = phone_cfg.get('value', '')
    phone_bcd = encode_bcd(str(phone_value), 12)  # 2013版本固定12位
    
    # 消息流水号 WORD（state.seq 自增）
    seq = int(state.get('seq', 0)) & 0xFFFF
    state['seq'] = (seq + 1) & 0xFFFF
    seq_bytes = write_uint(seq, 2)
    
    # 组装header（不含分包项）
    header = msg_id + body_attr + phone_bcd + seq_bytes
    return header


def build_header_2019(frame_id: int, body_length: int, common: dict, state: dict) -> bytes:
    """构建2019版本的协议头
    
    结构（17字节）：
    - 消息ID (WORD, 2字节)
    - 消息体属性 (WORD, 2字节, bit14=1)
    - 协议版本号 (BYTE, 1字节, 固定为1)
    - 终端手机号 (BCD[10], 10字节)
    - 消息流水号 (WORD, 2字节)
    """
    # 消息ID WORD
    msg_id = write_uint(frame_id, 2)
    
    # 消息体属性 WORD（bit14=1，表示有版本标识）
    body_attr_value = _build_msg_body_attr_2019(body_length)
    body_attr = write_uint(body_attr_value, 2)
    
    # 协议版本号 BYTE 固定1
    version = bytes([1])
    
    # 终端手机号 BCD[10]（20位数字，10字节）
    phone_cfg = common.get('terminal_phone', {})
    phone_value = phone_cfg.get('value', '')
    phone_digits = int(phone_cfg.get('digits', 20))
    phone_bcd = encode_bcd(str(phone_value), phone_digits)
    
    # 消息流水号 WORD（state.seq 自增）
    seq = int(state.get('seq', 0)) & 0xFFFF
    state['seq'] = (seq + 1) & 0xFFFF
    seq_bytes = write_uint(seq, 2)
    
    # 组装header（不含分包项）
    header = msg_id + body_attr + version + phone_bcd + seq_bytes
    return header


def build_header(frame_id: int, body_length: int, common: dict, state: dict, 
                 header_version: str = "2019") -> bytes:
    """构建协议头（统一入口）
    
    Args:
        frame_id: 消息ID
        body_length: 消息体长度
        common: 通用配置
        state: 状态信息
        header_version: header版本 ("2013" 或 "2019")
        
    Returns:
        header字节数据
    """
    if header_version == "2013":
        return build_header_2013(frame_id, body_length, common, state)
    elif header_version == "2019":
        return build_header_2019(frame_id, body_length, common, state)
    else:
        logging.warning(f"未知的header版本: {header_version}，使用2019版本")
        return build_header_2019(frame_id, body_length, common, state)


def parse_header_2013(data: bytes, common: Dict[str, Any]) -> Tuple[Dict[str, Any], int]:
    """解析2013版本的协议头
    
    结构（12字节）：
    - [0-1] 消息ID (WORD)
    - [2-3] 消息体属性 (WORD, bit14=0)
    - [4-9] 终端手机号 (BCD[6], 12位数字)
    - [10-11] 消息流水号 (WORD)
    """
    if len(data) < 12:
        raise ValueError('数据长度不足，无法解析2013版本头部（需要至少12字节）')
    
    # 消息ID
    msg_id = int.from_bytes(data[0:2], 'big')
    
    # 消息体属性
    body_attr = int.from_bytes(data[2:4], 'big')
    
    # 终端手机号 BCD[6]（12位数字）
    phone_bytes = data[4:10]
    phone_hex = ''.join(f"{(b>>4)&0x0F}{b&0x0F}" for b in phone_bytes)
    phone_hex = phone_hex[:12].lstrip('0') or '0'
    
    # 消息流水号
    seq = int.from_bytes(data[10:12], 'big')
    
    header_len = 12
    
    return {
        'msgId': f"0x{msg_id:04x}",
        'bodyAttr': f"0x{body_attr:04x}",
        'version': None,  # 2013版本无此字段
        'terminalPhone': phone_hex,
        'seq': seq,
        'headerLen': header_len,
        'detectedHeaderVersion': '2013'
    }, header_len


def parse_header_2019(data: bytes, common: Dict[str, Any]) -> Tuple[Dict[str, Any], int]:
    """解析2019版本的协议头
    
    结构（17字节）：
    - [0-1] 消息ID (WORD)
    - [2-3] 消息体属性 (WORD, bit14=1)
    - [4] 协议版本号 (BYTE)
    - [5-14] 终端手机号 (BCD[10], 20位数字)
    - [15-16] 消息流水号 (WORD)
    """
    if len(data) < 17:
        raise ValueError('数据长度不足，无法解析2019版本头部（需要至少17字节）')
    
    # 消息ID
    msg_id = int.from_bytes(data[0:2], 'big')
    
    # 消息体属性
    body_attr = int.from_bytes(data[2:4], 'big')
    
    # 协议版本号
    version = data[4]
    
    # 终端手机号 BCD[10]（20位数字）
    phone_digits = int(common.get('terminal_phone', {}).get('digits', 20))
    phone_bytes = (phone_digits + 1) // 2
    start_phone = 5
    end_phone = start_phone + phone_bytes
    
    if len(data) < end_phone + 2:
        raise ValueError('数据长度不足，无法解析完整的2019版本头部')
    
    # 解析BCD电话号码
    phone_hex = ''.join(f"{(b>>4)&0x0F}{b&0x0F}" for b in data[start_phone:end_phone])
    phone_hex = phone_hex[:phone_digits].lstrip('0') or '0'
    
    # 消息流水号
    seq = int.from_bytes(data[end_phone:end_phone+2], 'big')
    
    header_len = end_phone + 2
    
    return {
        'msgId': f"0x{msg_id:04x}",
        'bodyAttr': f"0x{body_attr:04x}",
        'version': version,
        'terminalPhone': phone_hex,
        'seq': seq,
        'headerLen': header_len,
        'detectedHeaderVersion': '2019'
    }, header_len


def parse_header(data: bytes, common: Dict[str, Any]) -> Tuple[Dict[str, Any], int]:
    """解析协议头（统一入口，自动识别版本）
    
    Args:
        data: 原始数据帧字节
        common: 通用配置
        
    Returns:
        (header信息字典, header长度)
        
    Raises:
        ValueError: 数据长度不足或格式错误
    """
    if len(data) < 4:
        raise ValueError('数据长度不足，无法解析头部（需要至少4字节）')
    
    # 读取消息体属性，自动识别header版本
    body_attr = int.from_bytes(data[2:4], 'big')
    detected_version = detect_header_version(body_attr)
    
    logging.debug(f"检测到header版本: {detected_version}")
    
    # 根据检测到的版本调用相应的解析函数
    if detected_version == "2013":
        return parse_header_2013(data, common)
    else:  # "2019"
        return parse_header_2019(data, common)

